/*
 * Util
 */
if (!Util) {
    var Util = {};
}

/*Tab Menu*/
Util.TabMenu = function(domEL,data,callback,oConfig){
    this.dom = domEL;
    this.mod;
    this.tabs = [];
    this.dMenus = null;
    this.dPanels = null;
    this.disableMask = null;
    this.data = data||[];
    this.cfg = {
        width:110,
        autoResize:false,
        marginRightWidth:0,//tablist width
        disable:false,
        customCls:'',
        switchType:'hide', //'position'
        isExcuteCallbackAtInit:true,
        tabsList:false,
        closeAction:'hide', //'remove'
        autoFixtoText: true,
        vertical: false,
        activeTabId: null,
        activeTabIndex: 0,//if some tabs include same id, then this args stand for the index of the same id tab
        tabsMask: false,
		needTitle:false,
        autoSlideToActiveTab: true,
		plusSymbol:false,
        rearrange: false
    };
    if(oConfig) {
        $.extend(this.cfg, oConfig);
    }
    this.callback = callback||{}; //{onActive, onDeActive, beforeClose, afterClose, afterRearrange,onAddTab}
    this.currentTab = null;
    this._panelHeight = 500;
    this._panelWidth = '100%';
    this._tabWidth = this.cfg.width;
	this.plusTabRightEl = null;
	this.plusTabInTabEl = null;
    this.showPlusinTab=true;
    this.marginRightWidth = [22,44];
    this.init();
};
Util.TabMenu.prototype = {
    init:function(){
        var self = this;
        this.mod = $('<div class="rtq-tabs'+(this.cfg.vertical?' rtq-tabs-v':'')+'">');
        this.dMenus = $('<ul class="rtq-tab-menus">');
        this.mod.append('<div class="rtq-tab-wrap"><div class="rtq-tab-tablist">'+(this.cfg.plusSymbol?'<a class="qs-tabmenu-plus qs-tabmenu-plus-right"></a>':'')+'</div><div class="rtq-tab-menus-wrap"></div></div>');
        this.tableListWrap = this.mod.find(".rtq-tab-tablist");
		
	    this.menusWrap = this.mod.find('.rtq-tab-menus-wrap').append(this.dMenus);
		this.plusTabRightEl = this.tableListWrap.find(".qs-tabmenu-plus-right");
        this.disableMask = this.mod.append('<div class="rtq-tab-mask"></div>');
        if(this.cfg.tabsList){
            this.tabList = new Util.DropDownList(this.mod.find('.rtq-tab-tablist'), function(t,v,index){
                self.cfg.activeTabIndex=index;
                self.getTabById(v).active();
            }, {},{width:22,syncListWidth:false,actionAtInit:false,ellipsis:true});
        }else{
            this.marginRightWidth[0]=0;
        }
		if(this.cfg.plusSymbol){
            this.plusTabRightEl.bind("click", function(){
                self._onClickPlusTab();
            });
            this._createPlusObj();
		}
        this.dPanels = $('<div class="rtq-tab-panels">').appendTo(this.mod);
        if(this.cfg.tabsMask){
            this.menusWrap.append('<div class="rtq-tab-mask-l"></div><div class="rtq-tab-mask-r"></div>');
        }
        if(this.cfg.customCls!=''){
            this.mod.addClass(this.cfg.customCls);
            this.dMenus.addClass(this.cfg.customCls + '-menus');
            this.dPanels.addClass(this.cfg.customCls + '-panels');
            this.mod.find('.rtq-tab-wrap').addClass(this.cfg.customCls + '-wrap');
            this.mod.find('.rtq-tab-mask-r').addClass(this.cfg.customCls + '-mask-r');
            this.mod.find('.rtq-tab-mask-l').addClass(this.cfg.customCls + '-mask-l');
            this.menusWrap.addClass(this.cfg.customCls + '-menus-wrap');
        }
        if (this.cfg.rearrange) {
            this.dropTip = $('<div class="drop-tip"></div>').appendTo(this.menusWrap);
        }
        this.mod.appendTo(this.dom);
        if(this.cfg.plusSymbol&&this.plusTabRightEl){
            this.marginRightWidth[1]=this.plusTabRightEl.outerWidth(true)+this.marginRightWidth[0];
        }
        this.plusTabRightEl.css("display", "none");
        if(this.cfg.marginRightWidth>0){
            this.marginRightWidth[1]=this.cfg.marginRightWidth+this.plusTabRightEl.outerWidth(true);
            this.marginRightWidth[0]=this.cfg.marginRightWidth;
        }
        if(this.cfg.tabsList){
            this.menusWrap[0].style.marginRight = this.marginRightWidth[0]+'px';
        }
        this._bindData(this.data);
        this._resizeTabMenu();
    },
	_onClickPlusTab:function(){
		if(typeof(this.callback.onAddTab)=="function"){
			this.callback.onAddTab();
		}
	},
	reSize:function(){
        this._resizeTabMenu();
	},
	_createPlusObj:function(){
		var tab = {id:"plus"};
        var self = this;
		tab.menu = $('<li class="qs-tabmenu-plus-tab"></li>').html('<a class="qs-tabmenu-plus"></a>');
		this.plusTabInTabEl = tab.menu;
		this.plusTabInTabEl.find(".qs-tabmenu-plus").bind("click",function(){
			self._onClickPlusTab();
		})
		this.dMenus.append(tab.menu);
		return tab;
	},
    _createTabObj:function(objProfile){ //{txt:Name, id:123}
        var tab = {};
        var self = this;
        tab.isClose = false;
        tab.closable = true;
        tab.disabled = false;
        $.extend(tab, objProfile);
        tab.id = typeof objProfile.id == 'undefined' ? objProfile.val :objProfile.id;
        tab.menu = $('<li class="menu'+ (!tab.closable?' noclose':'') + (tab.disabled?' disabled':'') + '" >').html('<a><span>'+objProfile.txt + '</span><em title="Close this Tab.">x</em></a>');
		if(this.cfg.needTitle){
			tab.menu.find("a span").attr("title",objProfile.txt);
		}
        if(!this.cfg.autoFixtoText){
            tab.menu.width(self.cfg.width);
        }
        tab.panel = $('<div class="rtq-tab-panel">');
        if(self.cfg.customCls!=''){
            tab.panel.addClass(self.cfg.customCls + '-panel');
        }
        //function
		tab.reName =function(name){
			tab.menu.find("a span").text(name);
			if (self.cfg.needTitle) {
				tab.menu.find("a span").attr("title", name);
			}
			tab.menu.width("auto");
		},
        tab.active = function(e,noExcuteCallbak){
            if ((self.currentTab && self.currentTab == tab) || tab.disabled) {
                return;
            }else {
                if (self.currentTab) {
                    self.currentTab.deactive();
                }
                self.currentTab = tab;
                tab.menu.addClass('on');
                
                if (self.cfg.switchType == 'position') {
                    tab.panel.css({
                        position: 'relative',
                        left: 0,
                        width: self._panelWidth,
                        height: self._panelHeight
                    });
                }else{
                    tab.panel.show();
                }
                
                if(tab.isClose){
                    tab.menu.show();
                    tab.isClose = false;
                }
                self.cfg.activeTabIndex = self.getTabIndex();
                if(self.tabList){
                    self.tabList.setTextValue(null, tab.id,self.cfg.activeTabIndex);
                }
                self._adjustPlus();
                //custom event
                if (self.callback.onActive && !noExcuteCallbak) {
                    self.callback.onActive(tab);
                }
            }
        };
        tab.deactive = function(e){
            if (self.callback.onDeActive) {
                self.callback.onDeActive(tab);
            }
            tab.menu.removeClass('on');
            if (self.cfg.switchType == 'position') {
                tab.panel.css({
                    position: 'absolute',
                    left: -10000
                });
            }else{
                tab.panel.hide();
            }
        };
        tab.close = function(){
            //custom event
            if (self.callback.beforeClose) {
                self.callback.beforeClose(tab);
            }
            if (tab.closable) {
                tab.deactive();
                tab.menu.hide();
                tab.isClose = true;
                if(tab.id == self.currentTab.id || self.currentTab == null){
                    self.currentTab = null;
                    self._activeNextTab(tab.index);
                }
                self._resizeTabMenu();
                self.reBindTabList();
            }
            //custom event
            if (self.callback.afterClose) {
                self.callback.afterClose(tab);
            }
        };
        //event
        tab.menu.click(function(e){
            if(self.cfg.disable == true){
                return false;
            }
            var target = $(e.target);
            switch(e.target.tagName.toLowerCase()){
                case 'span':{
                    tab.active(e);
                }break;
                case 'li':{
                    tab.active(e);
                }break;
                case 'a':{
                    tab.active(e);
                }break;
                case 'em':{
                    if (self.cfg.closeAction == 'remove') {
                        self.removeTab(tab, true);
                    }
                    else {
                        tab.close(e);
                    }
                }break;
            }
        }).hover(
            function(e){
                $(this).addClass('over');
            },
            function(e){
                $(this).removeClass('over');
            }
        );

        if (this.cfg.rearrange) {
            var drag = new Util.Dragable(tab.menu, {
                onDragStart: function(e, proxy){
                    tab.menu.addClass('ondrag');
                    proxy.dragingTab = tab;
                    proxy.html(tab.txt);
                    proxy.hide();
                },
                onDrag: function(e, proxy){
                    if (proxy.droppingTab) {
                        var offset = proxy.droppingTab.menu.offset();
                        var width = proxy.droppingTab.menu.width();
                        //determind show tip at left or right 
                        if (e.clientX < offset.left + width / 2) {
                            self.dropTip.css({
                                left: proxy.droppingTab.menu.position().left - 2,
                                display: 'block'
                            });
                        }
                        else {
                            self.dropTip.css({
                                left: proxy.droppingTab.menu.position().left + width,
                                display: 'block'
                            });
                        }
                    }
                    proxy.css({
                        top: self.menusWrap.offset().top + 3,
                        display: 'block'
                    });
                },
                onDragEnd: function(e, proxy){
                    tab.menu.removeClass('ondrag');
                }
            }, {
                group: 'QS_TABMENU',
                customClass: 'rtq-tabs-dd-proxy',
                delay: 30
            });
            var drop = new Util.Dropable(tab.menu, {
                onEnter: function(e, proxy){
                    tab.menu.addClass('ondrop');
                    proxy.droppingTab = tab;
					if (self.callback.beforeRearrange) {
                        self.callback.beforeRearrange(tab);
                    }
                },
                onDrop: function(e, proxy){
                    if (proxy.dragingTab != tab && proxy.droppingTab) {
                        //insert tab to target
                        var offset = proxy.droppingTab.menu.offset();
                        var width = proxy.droppingTab.menu.width();
                        var insertToIdx = 0;
                        //for animate
                        var tabOrigWidth = proxy.dragingTab.menu.width();
                        proxy.dragingTab.menu.width(0);
                        //determind insert to left or right 
                        if (e.clientX < offset.left + width / 2) {
                            proxy.dragingTab.menu.insertBefore(tab.menu);
                            insertToIdx = tab.index;
                        }
                        else {
                            proxy.dragingTab.menu.insertAfter(tab.menu);
                            insertToIdx = tab.index + 1;
                        }
                        if (proxy.dragingTab.index < tab.index) {
                            insertToIdx--;
                        }
                        proxy.dragingTab.menu.animate({
                            width: tabOrigWidth
                        }, {
                            duration: 200
                        });
                        //---reorder the tabs arrray---[
                        //del
                        self.tabs.splice(proxy.dragingTab.index, 1);
                        //insert
                        self.tabs.splice(insertToIdx, 0, proxy.dragingTab);
                        //reset tab.index
                        for (var i = 0, l = self.tabs.length; i < l; i++) {
                            self.tabs[i].index = i;
                        }
                        //]---reorder the tabs arrray---
                        self.reBindTabList();
                        //custom event
                        if (self.callback.afterRearrange) {
                            self.callback.afterRearrange(tab);
                        }
                    }
                    self.dropTip.hide();
                    tab.menu.removeClass('ondrop');
                    proxy.droppingTab = null;
                },
                onOut: function(e, proxy){
                    self.dropTip.hide();
                    tab.menu.removeClass('ondrop');
                    proxy.droppingTab = null;
                }
            }, {
                group: 'QS_TABMENU'
            });
        }

        //custom event
        if (self.callback.onTabRender) {
            self.callback.onTabRender(tab);
        }
        return tab;
    },
    _resizePlusPosition:function(){
        Util.DelayRun('resizePlus',function(){
            var viewPortWidth = this.menusWrap.outerWidth(true)-this.marginRightWidth[0];
            var menusWidth = this.dMenus.outerWidth();
            if (menusWidth > viewPortWidth) {//view right plus
                if(this.showPlusinTab){
                    this.plusTabRightEl.css("display", "block");
                    this.plusTabInTabEl.css("visibility", "hidden");
                    this.menusWrap[0].style.marginRight = this.marginRightWidth[1]+'px';
                    this.showPlusinTab=false;
                }
            }else{
                this.plusTabRightEl.css("display", "none");
                this.plusTabInTabEl.css("visibility", "visible");
                this.menusWrap[0].style.marginRight = this.marginRightWidth[0]+'px';
                this.showPlusinTab=true;
            }
        },100,this);
    },
    _checkTabPosition:function(tab){
        var tabMenu = tab.menu;
        Util.DelayRun('slidetotab', function(){
            if (!this.cfg.vertical) {
                var tabWidth = tabMenu.outerWidth(true);
                if (tabWidth > 0) {
                    var wrapoffset = this.menusWrap.offset().left;
                    var positionLeft=tabMenu.offset().left-wrapoffset,tabsWidth=this.menusWrap.width();
                    //console.log("tabMenu.offset:"+tabMenu.offset().left);
                    //console.log("menusWrap.offset"+wrapoffset);
                    if(this.currentMenuLeft==positionLeft+tabWidth&&this.tabsWidth==tabsWidth) return;//prevent reposition
                    var offsetRight= positionLeft+tabWidth+this.menusWrap.scrollLeft();
                    //console.log("positionLeft:"+positionLeft);
                    //console.log("scrollLeft"+this.menusWrap.scrollLeft());
                    this.tabsWidth = tabsWidth;
                    var tarScrollLeft = this._hasNext(tab)?(offsetRight-tabsWidth+30):(offsetRight-tabsWidth);
                    //console.log("offsetRight:"+offsetRight);
                    //console.log("tabsWidth:"+tabsWidth);
                    var self=this;
                    if (offsetRight > this.tabsWidth) {
                        this.menusWrap.animate({
                            scrollLeft: tarScrollLeft
                        },function(){
                           self.currentMenuLeft = tabMenu.offset().left-wrapoffset+tabWidth;
						});
                    }
                    else {
                        this.menusWrap.animate({
                            scrollLeft: 0
                        },function(){
                            self.currentMenuLeft = tabMenu.offset().left-wrapoffset+tabWidth;
                        });
                    }
                }
            }
        }, 200, this);
    },
    _activeNextTab:function(index, direction){
        if(this.tabs.length < 2){
            return;
        }
        direction = direction||'next'; //'prev'
        var nextTab = direction=='next'?this.tabs[(index>0)?index-1:1]:this.tabs[(index<this.tabs.length)?index+1:0];//can't change the logic
        if (nextTab) {
            if (nextTab.isClose) {
                if (nextTab.index == 0) {
                    this._activeNextTab(nextTab.index, 'prev');
                }
                else {
                    this._activeNextTab(nextTab.index, direction);
                }
            }
            else {
                nextTab.active(null, false);
            }
        }
    },
    _hasNext:function(tab){
        var index=tab.index;
        var nextTab = this.tabs[index+1];
        if (nextTab) {
            if (nextTab.isClose) {
                return this._hasNext(nextTab);
            }
            else {
                return true;
            }
        }else{
            return false;
        }
    },
    _resizeTabMenu:function(){
        var self = this;      
        Util.DelayRun('resizeTabmenu',function(){
            if (self.cfg.autoResize) {
                var w = self.menusWrap.width();
                var l = 0;
                for(var i=0;i<self.tabs.length;i++){
                    if(!self.tabs[i].isClose){
                        l++;
                    }
                }
                if(!self.tabs||self.tabs.length<1){
                    return;
                }//edit by wind 20100118
                var tw = self.tabs[0].menu.width();
                if (tw <= self.cfg.width && w > self.cfg.width * (l+1)) {
                    self.setTabWidth(self.cfg.width);
                }
                else {
                    self.setTabWidth(w / l - 5);
                }
            }
            self._adjustPlus();
        },200,self);
    },
    _adjustPlus:function(){
        if(this.cfg.plusSymbol){
            this._resizePlusPosition();
        }
        if (this.cfg.autoSlideToActiveTab) {
            this.showActiveTab();
        }
    },
    showActiveTab:function(){
        if (this.currentTab) {
            this._checkTabPosition(this.currentTab);
        }
    },
    getIdList:function(){
        var ids = [];
        for (var i = 0, l = this.tabs.length; i < l; i++) {
            if(!this.tabs[i].isClose){
                ids.push(this.tabs[i].id)
            }
        }
        return ids;
    },
    _bindData:function(data){
        this.data = data;
        var tab=null;
        for(var i=0,l=this.data.length;i<l;i++){
            tab = this._createTabObj(this.data[i]);
            tab.dataindex=i;
            this._addTab(tab);
        }
        if (this.tabs.length > 0) {
            var activeTab = this.getTabById(this.cfg.activeTabId)||this.tabs[0];
			if(activeTab.active){
				activeTab.active(null,!this.cfg.isExcuteCallbackAtInit);
			}
        }
        for(var i=0,l=this.tabs.length;i<l;i++){
            this.tabs[i].index = i;
        }
        this.reBindTabList();
    },
    reBindData:function(data){
		this.menusWrap.scrollLeft(0);//reset tab position,alex,2011.12.28
        this.currentTab = null;
        for(var i=this.tabs.length-1;i>=0;i--){
            this._removeTab(this.tabs[i]);
        }
        this.tabs.length = 0;
        this._bindData(data.slice());
        this._resizeTabMenu();
    },
    reBindTabList:function(){
        if(this.tabList){
            var data = []
            for (var i = 0, l = this.tabs.length; i < l; i++) {
                if (!this.tabs[i].isClose) {
                    data.push({val:this.tabs[i].id, txt:this.tabs[i].txt});
                }
            }
            this.tabList.rebindData(data);
            if (this.currentTab) {
                this.tabList.setTextValue(this.currentTab.txt, this.currentTab.id,this.getTabIndex());
            }
        }
    },
    _addTab:function(tabObj,index){
        if(typeof index == 'undefined'){
            if(this.cfg.plusSymbol){
                this.plusTabInTabEl.before(tabObj.menu);
            }else{
                this.dMenus.append(tabObj.menu);
            }
        }else{
            if(this.tabs.length>0){
                this.dMenus.find('li').eq(index).before(tabObj.menu);
                //this.dPanels.find('.rtq-tab-panel').eq(index).before(tabObj.panel);
            }else{
                if(this.cfg.plusSymbol){
                    this.plusTabInTabEl.before(tabObj.menu);
                }else{
                    this.dMenus.append(tabObj.menu);
                }
            }
        }
        this.dPanels.append(tabObj.panel);
        var length=this.tabs.length;
        if(typeof index == 'undefined'){
            this.tabs.push(tabObj);
        }else{
            this.tabs.splice(index,0,tabObj);
        }
    },
    addTab:function(tabProfile,index){
        this.data.push(tabProfile);
        var tab = this._createTabObj(tabProfile);
        tab.dataindex=this.data.length-1;
        this._addTab(tab,index);
        for(var i=0,l=this.tabs.length;i<l;i++){
            this.tabs[i].index = i;
        }
        this.reBindTabList();
        this._resizeTabMenu();
        return tab;
    },
    _removeTab:function(tabObj){
        //tabObj.close();
        this.cfg.activeTabIndex=0;
        tabObj.menu.remove();
		if(tabObj.panel){
			tabObj.panel.remove();
		}
    },
	reNameCurTab:function(name){
		this.currentTab.reName(name);
	},
    removeTabs:function(tabs,isExcuteCallback){
        for(var i=0,l=tabs.length;i<l;i++){
            this.removeTab(tabs[i],isExcuteCallback);
        }
    },
    removeTab:function(tabObj, isExcuteCallback){
		if(!tabObj){
			return;
		}
        var dataindex=tabObj.dataindex;
        this.data.splice(dataindex, 1);
        /*
        for(var i=0,l=this.data.length;i<l;i++){
            if(this.data[i].id == tabObj.id || this.data[i].val == tabObj.id){
                this.data.splice(i, 1);
                break;
            }
        }
        */
        if(isExcuteCallback===true){
            tabObj.close();
        }
        this._removeTab(tabObj);
        this.tabs.splice(tabObj.index, 1);
        delete tabObj;
        for(var i=0,l=this.tabs.length;i<l;i++){
            this.tabs[i].index = i;
            if(this.tabs[i].dataindex>dataindex){
                this.tabs[i].dataindex--;
            }
        }
    },
    changeToTab:function(tab){
        tab.active(null);
    },
    getTabById:function(id){
        var count = this.cfg.activeTabIndex;//flag the index of the same id tab
        for(var i=0,l=this.tabs.length;i<l;i++){
            if(this.tabs[i].id == id){
                count--;
                if(count<0){
                    return this.tabs[i];
                }
            }
        }
        return null;
    },
    getTabsByid:function(id){
        var tabs=[];
        for(var i=0,l=this.tabs.length;i<l;i++){
            if(this.tabs[i].id == id){
                tabs.push(this.tabs[i]);
            }
        }
        return tabs;
    },
    getTabByIndex:function(index){
        for(var i=0,l=this.tabs.length;i<l;i++){
            if(this.tabs[i].index == index){
                return this.tabs[i];
            }
        }
        return null;
    },
    changeTabByIndex:function(i,isExcuteCallback){
        var tab=this.getTabByIndex(i);
        tab.active(null,!isExcuteCallback);
    },
	changeTabById:function(id,isExcuteCallback){
		this.getTabById(id).active(null,!isExcuteCallback);
	},
    setPanelOutSize:function(w,h){
        this._panelHeight = h;
        this._panelWidth = w;
        if (this.currentTab) {
            this.currentTab.panel.css({
                width: w,
                height: h
            });
        }
    },
    getTabIndex:function(tab){
        var count=0;
        if(!tab) tab=this.currentTab;
        for (var i = 0, l = this.tabs.length; i < l; i++) {
            if(tab.id==this.tabs[i].id&&!this.tabs[i].isClose){
                if(tab==this.tabs[i]){
                    return count;
                }
                count++;
            }
        }
    },
    setDisable: function(isDisable){
        this.cfg.disable = isDisable === false ? false : true;
        if(this.cfg.disable){
            this.mod.addClass('rtq-tabs-disable')
        }else{
            this.mod.removeClass('rtq-tabs-disable')
        }
    },
    setTabWidth:function(w){
        if (w > 0 && !this.cfg.autoFixtoText) {
            this._tabWidth = w;
            for (var i = 0, l = this.tabs.length; i < l; i++) {
                this.tabs[i].menu.css({
                    width: w
                });
            }
        }
    },
	clear:function(){
		if(this.tabs){
			for(var o in this.tabs){
				if(this.tabs[o].menu)this.tabs[o].menu.unbind();
				this.tabs[o].active = this.tabs[o].deactive = this.tabs[o].close = null;
			}
		}
		if(this.tabList&&typeof(this.tabList.clear)=="function"){
			this.tabList.clear();
		}
		this.mod.remove();
		this.mod = null;
	}
};
//var tbb = new Util.TabMenu($('#x-desktop')[0], [{id:1,txt:'tab1'},{id:2,txt:'tab2'}]);